#include "include.h"
#include "func.h"
#include "func_device.h"

#define TRACE_EN                1

#if TRACE_EN
#define TRACE(...)              printf(__VA_ARGS__)
#define TRACE_R(...)            print_r(__VA_ARGS__)
#else
#define TRACE(...)
#define TRACE_R(...)
#endif // TRACE_EN

enum {
    DEVICE_STA_INIT_IDLE,
    DEVICE_STA_INIT_CONNECT,
    DEVICE_STA_START_ACTION,
    DEVICE_STA_DELAY,

    DEVICE_STA_IDLE,
    DEVICE_STA_SCAN,
};

static struct {
    uint8_t init_flag;
    uint8_t init_state;
    uint8_t con_state;
    uint32_t ticks;
    uint tick_delay;
} device_cb;

#if WIRELESS_MIC_TX_EN
//无线MIC发射端处理流程
//MIC_ADC -> encoder_prio_trans_audio_input --> mic_enc_audio_input -> wireless_d2a_put_tx_frame -> memcpy(txbuf, enc_buf, size) -> DEVICE_TX
//                                          |-> dac0_out_audio_input -> DAC
static ws_link_list_t mic_tx_cfg_tbl[] = {
/*  模块类型，                  使能，          初始化，                  输入接口，                       设置输出*/
#if !DEVICE_MIX_AUX_EN
    {MIC_TYPE,                  1,              mic_init,                 NULL,                            mic_audio_output_callback_set},
#else
    {MIC_MIX_AUX_TYPE,          1,              mic_mix_aux_init,         NULL,                            mic_mix_aux_audio_output_callback_set},
#endif
    {ENCODER_PRIO_TRANS_TYPE,   1,              encoder_prio_trans_init,  encoder_prio_trans_audio_input,  encoder_prio_trans_audio_output_callback_set},    //缓存到编码缓冲区，并转到低优先级处理
#if HUART_DUMP_AUDIO
    {HUART_DUMP_TYPE,           1,              huart_dump_init,          huart_dump_audio_input,          huart_dump_audio_output_callback_set},
#endif
#if WIRELESS_MIC_AINS3_EN
    {AINS_TYPE,                 1,              ains3_mic_init,           ains3_mic_audio_input,           ains3_mic_output_callback_set},                      //PCM编码
#endif

#if WIRELESS_MIC_DNN_L1_EN
    {DNN_L1_TYPE,            1,              dnn_L1_mic_init,          dnn_L1_mic_audio_input,          dnn_L1_mic_output_callback_set},                      //PCM编码
#endif

#if WIRELESS_MIC_DRC_EN
    {EQ_DRC_TYPE,               1,              mic_eq_drc_init,          mic_eq_drc_audio_input,          mic_eq_drc_audio_output_callback_set},               //EQ
#endif
#if WIRELESS_MIC_ECHO_EN
    {ECHO_TYPE,                 1,              echo_audio_init,          echo_audio_input,                echo_audio_output_callback_set},
#endif
#if WIRELESS_MIC_MAGIC_EN
    {MAGCI_PITCH_SHIFT_TYPE,    1,              magic_audio_init,         magic_audio_input,               magic_audio_output_callback_set},
#endif

#if WIRELESS_MIC_LOCAL_OUTPUT_EN
    {DAC_OUT_TYPE,              1,              dac_out_init,             dac_out_audio_input,             dac_out_audio_output_callback_set},
#endif
    {MIC_ENC_TYPE,              1,              mic_enc_init,             mic_enc_audio_input,             mic_enc_audio_output_callback_set},                  //PCM编码
};
#endif

#if WIRELESS_SPK_TX_EN
static ws_link_list_t spk_rx_cfg_tbl[] = {
/*  模块类型，                  使能，          初始化，                  输入接口，                       设置输出*/
    {DECODER_PRIO_TRANS_TYPE,   1,              decoder_prio_trans_init,  NULL,                            decoder_prio_trans_audio_output_callback_set},
    {SPK_DEC_TYPE,              1,              spk_dec_init,             spk_dec_audio_input,             spk_dec_audio_output_callback_set},             //PCM解码
#if DEVICE_DAC_OUTPUT_EN
    {DAC_OUT_TYPE,              1,              dac_out_init,             dac_out_audio_input,             dac_out_audio_output_callback_set},
#endif
};
#endif

AT(.text.func.device_cb)
void func_device_init(void)
{
    if (!device_cb.init_flag) {
        device_cb.init_flag = 1;
#if WIRELESS_MIC_TX_EN
        ws_link_list_init(mic_tx_cfg_tbl, (sizeof(mic_tx_cfg_tbl)/sizeof(ws_link_list_t)), WIRELESS_MIC_SAMPLE_RATE_SELECT, WIRELESS_MIC_SAMPLES_SELECT);
#endif

#if WIRELESS_SPK_TX_EN
        ws_link_list_init(spk_rx_cfg_tbl, (sizeof(spk_rx_cfg_tbl)/sizeof(ws_link_list_t)), WIRELESS_SPK_SAMPLE_RATE_SELECT, WIRELESS_SPK_SAMPLES_SELECT);
#endif
    }

    device_cb.init_state = DEVICE_STA_INIT_IDLE;
}

AT(.text.func.device)
static void func_device_process_do(void)
{
    u8 addr[6];

    if(wireless_cb.change_flag) {
        wireless_cb.change_flag = 0;

        switch(wireless_cb.change_sta[0]) {
        case 0:     //connect success
            device_cb.init_state = DEVICE_STA_START_ACTION;
            break;

        case 1:     //connect fail
            if(!wireless_mic_is_bonding()
               && device_cb.init_state == DEVICE_STA_INIT_CONNECT) {
                device_cb.init_state = DEVICE_STA_START_ACTION;
                break;
            }
            //no break

        case 2:     //disconnect
            device_cb.ticks      = tick_get();
            device_cb.tick_delay = 1000+bt_get_rand()%500;
            device_cb.init_state = DEVICE_STA_DELAY;
            break;
        }
    }

    switch(device_cb.init_state) {
    case DEVICE_STA_INIT_IDLE:
        TRACE("emit, init(%d)\n", wireless_mic_is_bonding());
        if(bt_get_link_info_addr(addr, 0)) {
            //有回连信息，开始回连
            TRACE("emit, con_req: ");
            TRACE_R(addr, 6);
            ble_create_con_for_addr(addr, 2500);
            device_cb.init_state  = DEVICE_STA_INIT_CONNECT;
        } else {
            //没有回连信息，搜索组队
            TRACE("emit, scan_en\n");
            ble_scan_set_enable(1);
            device_cb.init_state  = DEVICE_STA_SCAN;
            device_cb.ticks       = tick_get();
        }
        break;

    case DEVICE_STA_INIT_CONNECT:
        break;

    case DEVICE_STA_START_ACTION:
        TRACE("emit, con_sta(%d): %x\n", wireless_mic_is_bonding(), wireless_cb.connected_sta);

        if(wireless_cb.connected_sta) {
            //已连接，关闭扫描
            TRACE("emit, scan_dis\n");
            ble_scan_set_enable(0);
            device_cb.init_state = DEVICE_STA_IDLE;
        } else if(wireless_mic_is_bonding() && bt_get_link_info_addr(addr, 0)) {
            //有回连信息，开始回连
            TRACE("emit, con_req: ");
            TRACE_R(addr, 6);
            ble_create_con_for_addr(addr, 2500);
            device_cb.init_state  = DEVICE_STA_INIT_CONNECT;
        } else {
            //没有回连信息，搜索组队
            TRACE("emit, scan_en\n");
            ble_scan_set_enable(1);
            device_cb.init_state = DEVICE_STA_SCAN;
            device_cb.ticks      = tick_get();
        }
        break;

    case DEVICE_STA_SCAN:
//        if(tick_check_expire(device_cb.ticks, 4000)) {     //省电时可以间歇性扫描
//            ble_scan_set_enable(0);
//            device_cb.ticks      = tick_get();
//            device_cb.tick_delay = 1000+bt_get_rand()%500;
//            device_cb.init_state = DEVICE_STA_DELAY;
//        }
        break;

    case DEVICE_STA_DELAY:
        if(tick_check_expire(device_cb.ticks, device_cb.tick_delay)) {
            device_cb.init_state = DEVICE_STA_START_ACTION;
        }
        break;
    }
}

AT(.text.func.process.device)
static void func_device_process(void)
{
#if TRACE_EN
    static u8 sta = 0xff;
    if(sta != device_cb.init_state) {
        sta = device_cb.init_state;
        TRACE("emit, state: %d\n", sta);
    }
#endif
    if(device_cb.init_state != DEVICE_STA_IDLE || wireless_cb.change_flag) {
        func_device_process_do();
    }

    led_disp_proc();
    func_process();
}

AT(.text.func.device)
static void func_device_enter(void)
{
    func_device_init();
    func_bt_init();
}

AT(.text.func.device)
static void func_device_exit(void)
{
    le_mic_discon_all();
#if	!DEVICE_MIX_AUX_EN
    mic_stop();
#else
    mic_mix_aux_stop();
#endif
    bt_off();
    func_cb.last = FUNC_DEVICE;
    sys_cb.bt_is_inited = 0;
    device_cb.init_flag = 0;
}

AT(.text.func.device_cb)
void func_device(void)
{
    printf("%s\n", __func__);
    func_device_enter();

    while (func_cb.sta == FUNC_DEVICE) {
        func_device_process();
        func_device_message(msg_dequeue());
        //func_device_display();
    }

    func_device_exit();
}

